package com.hnhegui.backend.order.service;

import cn.hutool.core.util.ObjectUtil;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.ChildScoreMode;
import co.elastic.clients.elasticsearch._types.query_dsl.NestedQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
import co.elastic.clients.json.JsonData;
import com.hnhegui.backend.entity.Result;
import com.hnhegui.backend.exception.BusinessException;
import com.hnhegui.backend.merchant.api.ProductRestApi;
import com.hnhegui.backend.merchant.dto.request.FreezeStockRequestDTO;
import com.hnhegui.backend.merchant.dto.request.UnfreezeStockRequestDTO;
import com.hnhegui.backend.merchant.dto.response.ProductDetailsResponseDTO;
import com.hnhegui.backend.order.dto.request.AdminOrdersRequestDTO;
import com.hnhegui.backend.order.dto.request.CreateOrderRequestDTO;
import com.hnhegui.backend.order.dto.request.OrderDocumentPageRequestDTO;
import com.hnhegui.backend.order.dto.request.PayOrderRequestDTO;
import com.hnhegui.backend.order.dto.request.PaymentOrderCallbackRequestDTO;
import com.hnhegui.backend.order.dto.response.CreateOrderResponseDTO;
import com.hnhegui.backend.order.dto.response.PayOrderResponseDTO;
import com.hnhegui.backend.order.dto.response.PaymentOrderCallbackResponseDTO;
import com.hnhegui.backend.order.entity.OrderDocument;
import com.hnhegui.backend.order.enu.DeliveryTypeEnum;
import com.hnhegui.backend.order.enu.OrderStatusEnum;
import com.hnhegui.backend.order.repository.OrderRepository;
import com.hnhegui.backend.payment.api.PaymentRestApi;
import com.hnhegui.backend.payment.dto.request.PaymentRequestDTO;
import com.hnhegui.backend.payment.dto.response.PaymentResponseDTO;
import com.hnhegui.backend.utils.OrderNoGenerator;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ProductRestApi productRestApi;

    @Autowired
    private OrderNoGenerator orderNoGenerator;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private PaymentRestApi paymentRestApi;

    public CreateOrderResponseDTO createOrder(CreateOrderRequestDTO request) {
        // 验证配送类型和地址
        validateDeliveryInfo(request);

        // 创建订单文档
        OrderDocument order = new OrderDocument();
        order.setOrderId(UUID.randomUUID().toString());
        order.setOrderNo(orderNoGenerator.generateOrderNo());
        order.setUserId(request.getUserId());
        order.setStatus(OrderStatusEnum.PENDING_PAYMENT);
        order.setDeliveryType(request.getDeliveryType());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        // 处理订单商品
        List<OrderDocument.OrderItem> orderItems = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;

        for (CreateOrderRequestDTO.OrderItemRequest itemReq : request.getItems()) {
            Long productId = Long.parseLong(itemReq.getProductId());

            Result<ProductDetailsResponseDTO> productResult = productRestApi.getProductDetail(productId);
            if (!ObjectUtil.equals(productResult.getCode(), Result.RESULT_OK)) {
                throw new BusinessException(40401, "商品不存在: " + productId);
            }
            ProductDetailsResponseDTO product = productResult.getData();
            // 验证商品并锁定库存
            if (product == null) {
                throw new BusinessException(40401, "商品不存在: " + productId);
            }
            if (product.getStatus() == 0) {
                throw new BusinessException(40001, "商品已下架: " + product.getProductName());
            }
            if (product.getStock() < itemReq.getQuantity()) {
                throw new BusinessException(40002, "商品库存不足: " + product.getProductName());
            }

            // 冻结库存
            Result<Boolean> booleanResult = productRestApi.freezeStock(FreezeStockRequestDTO.builder()
                .freezeStock(itemReq.getQuantity())
                .orderId(order.getOrderId())
                .productId(productId)
                .build());
            if (!ObjectUtil.equals(booleanResult.getCode(), Result.RESULT_OK)) {
                throw new BusinessException(40002, "扣减库存失败，库存不足: " + product.getProductName());
            }
            if (booleanResult.getData()) {
                throw new BusinessException(40002, "扣减库存失败，库存不足: " + product.getProductName());
            }

            // 构建订单商品项
            OrderDocument.OrderItem orderItem = new OrderDocument.OrderItem();
            orderItem.setProductId(itemReq.getProductId());
            orderItem.setProductName(product.getProductName());
            orderItem.setQuantity(itemReq.getQuantity());
            orderItem.setPrice(itemReq.getPrice());
            orderItem.setSubtotal(itemReq.getPrice().multiply(new BigDecimal(itemReq.getQuantity())));

            orderItems.add(orderItem);
            totalAmount = totalAmount.add(orderItem.getSubtotal());
        }

        order.setItems(orderItems);
        order.setTotalAmount(totalAmount);

        // 设置收货地址
        if (request.getShippingAddress() != null) {
            unitAddress(request, order);
        }

        // 保存订单到ES
        try {
            orderRepository.save(order);
        } catch (Exception e) {
            // ES保存失败，回滚库存
            for (CreateOrderRequestDTO.OrderItemRequest itemReq : request.getItems()) {
                Long productId = Long.parseLong(itemReq.getProductId());
                productRestApi.unfreezeStock(UnfreezeStockRequestDTO.builder().orderId(order.getOrderId()).productId(productId).build());
            }
            throw new BusinessException(50001, "创建订单失败: " + e.getMessage());
        }

        // 构建响应
        CreateOrderResponseDTO response = new CreateOrderResponseDTO();
        response.setOrderId(order.getOrderId());
        response.setOrderNo(order.getOrderNo());
        response.setTotalAmount(order.getTotalAmount());
        response.setStatus(order.getStatus().name());
        response.setCreateTime(order.getCreateTime());

        return response;
    }

    private static void unitAddress(CreateOrderRequestDTO request, OrderDocument order) {
        OrderDocument.ShippingAddress address = new OrderDocument.ShippingAddress();
        address.setProvince(request.getShippingAddress().getProvince());
        address.setCity(request.getShippingAddress().getCity());
        address.setDistrict(request.getShippingAddress().getDistrict());
        address.setDetail(request.getShippingAddress().getDetail());
        address.setReceiverName(request.getShippingAddress().getReceiverName());
        address.setReceiverPhone(request.getShippingAddress().getReceiverPhone());
        order.setShippingAddress(address);
    }

    /**
     * 查询用户订单列表
     */
    public Page<OrderDocument> getUserOrders(OrderDocumentPageRequestDTO request) {

        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize(),
            Sort.by(Sort.Direction.DESC, "createTime"));

        if (request.getStatus() != null && !request.getStatus().isEmpty()) {
            return orderRepository.findByUserIdAndStatus(request.getUserId(), request.getStatus(), pageRequest);
        } else {
            return orderRepository.findByUserId(request.getUserId(), pageRequest);
        }
    }

    /**
     * 根据订单ID查询订单
     */
    public OrderDocument getOrderById(String orderId) {
        return orderRepository.findById(orderId)
            .orElseThrow(() -> new BusinessException(40401, "订单不存在"));
    }

    /**
     * 根据订单号查询订单
     */
    public OrderDocument getOrderByOrderNo(String orderNo) {
        OrderDocument order = orderRepository.findByOrderNo(orderNo);
        if (order == null) {
            throw new BusinessException(40401, "订单不存在");
        }
        return order;
    }

    /**
     * 更新订单
     */
    public void updateOrder(OrderDocument order) {
        order.setUpdateTime(LocalDateTime.now());
        orderRepository.save(order);
    }

    /**
     * 管理端多条件订单查询
     * @param request 请求入参
     * @return 分页结果
     */
    public Page<OrderDocument> searchAdminOrders(AdminOrdersRequestDTO request) {

        if (request.getPageSize() > 100) {
            request.setPageSize(100); // 限制最大每页条数
        }

        // 构建BoolQuery
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();

        String orderNo = request.getOrderNo();
        // 订单号精确匹配
        if (orderNo != null && !orderNo.trim().isEmpty()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("orderNo").value(orderNo)));
        }

        String userId = request.getUserId();
        // 用户ID精确匹配
        if (userId != null && !userId.trim().isEmpty()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("userId").value(userId)));
        }

        String status = request.getStatus();
        // 订单状态精确匹配
        if (status != null && !status.trim().isEmpty()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("status").value(status)));
        }

        String paymentStatus = request.getPaymentStatus();
        // 支付状态精确匹配
        if (paymentStatus != null && !paymentStatus.trim().isEmpty()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("paymentInfo.paymentStatus").value(paymentStatus)));
        }

        String receiverPhone = request.getReceiverPhone();
        // 收件人手机号精确匹配
        if (receiverPhone != null && !receiverPhone.trim().isEmpty()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("shippingAddress.receiverPhone").value(receiverPhone)));
        }

        String productName = request.getProductName();
        // 商品名称模糊匹配（嵌套查询）
        if (productName != null && !productName.trim().isEmpty()) {
            NestedQuery nestedQuery = NestedQuery.of(n -> n
                .path("items")
                .query(q -> q.match(m -> m
                    .field("items.productName")
                    .query(productName)
                ))
                .scoreMode(ChildScoreMode.Avg)
            );
            boolQueryBuilder.must(m -> m.nested(nestedQuery));
        }

        LocalDateTime startTime = request.getStartTime();
        LocalDateTime endTime = request.getEndTime();
        // 时间范围查询
        if (startTime != null || endTime != null) {
            RangeQuery.Builder rangeBuilder = new RangeQuery.Builder().field("createTime");

            if (startTime != null) {
                // 使用ISO格式的日期字符串，与ES中date_hour_minute_second格式匹配
                rangeBuilder.gte(JsonData.of(startTime.toString()));
            }

            if (endTime != null) {
                // 使用ISO格式的日期字符串，与ES中date_hour_minute_second格式匹配
                rangeBuilder.lte(JsonData.of(endTime.toString()));
            }

            boolQueryBuilder.filter(f -> f.range(rangeBuilder.build()));
        }

        // 构建最终查询
        Query query;
        BoolQuery boolQuery = boolQueryBuilder.build();

        // 如果没有任何条件,使用match_all查询
        if (boolQuery.filter().isEmpty() && boolQuery.must().isEmpty()) {
            query = Query.of(q -> q.matchAll(m -> m));
        } else {
            query = Query.of(q -> q.bool(boolQuery));
        }

        // 构建分页和排序
        PageRequest pageRequest = PageRequest.of(
            request.getPage() - 1,
            request.getPageSize(),
            Sort.by(Sort.Direction.DESC, "createTime")
        );

        // 构建NativeQuery，启用track_total_hits以获取准确的总数
        NativeQuery nativeQuery = NativeQuery.builder()
            .withQuery(query)
            .withPageable(pageRequest)
            .withTrackTotalHits(true) // 启用跟踪总命中数，解决ES默认只返回10000条总数的问题
            .build();

        // 执行查询
        SearchHits<OrderDocument> searchHits = elasticsearchTemplate.search(nativeQuery, OrderDocument.class);

        // 转换为Page对象
        List<OrderDocument> orders = searchHits.getSearchHits().stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());

        return new org.springframework.data.domain.PageImpl<>(
            orders,
            pageRequest,
            searchHits.getTotalHits()
        );
    }

    /**
     * 验证配送信息
     */
    private void validateDeliveryInfo(CreateOrderRequestDTO request) {
        if (request.getDeliveryType() == DeliveryTypeEnum.EXPRESS) {
            if (request.getShippingAddress() == null) {
                throw new BusinessException(40001, "快递配送必须提供收货地址");
            }
        } else if (request.getDeliveryType() == DeliveryTypeEnum.PICKUP) {
            if (request.getPickupStoreId() == null || request.getPickupStoreId().isEmpty()) {
                throw new BusinessException(40001, "门店自提必须指定门店");
            }
        }
    }

    public PayOrderResponseDTO payOrder(PayOrderRequestDTO request) {
        RLock lock = redissonClient.getLock("pay_order_" + request.getOrderId());
        if (!lock.tryLock()) {
            throw new BusinessException(40001, "请勿重复提交");
        }
        try{
            OrderDocument order = this.getOrderById(request.getOrderId());
            // 验证订单状态
            if (order.getStatus() != OrderStatusEnum.PENDING_PAYMENT) {
                throw new BusinessException(40001, "订单状态不正确，无法支付");
            }
            //拉起支付
            Result<PaymentResponseDTO> result = paymentRestApi.pay(PaymentRequestDTO.builder()
                .paymentMethod(request.getPaymentMethod())
                .orderId(request.getOrderId())
                .returnUrl(request.getReturnUrl())
                .build());
            Integer code = result.getCode();
            if (!ObjectUtil.equals(code, Result.RESULT_OK)) {
                //抛出异常，拉起支付失败
                throw new BusinessException(code, result.getMessage());
            }
            return PayOrderResponseDTO.builder()
                .paymentId(result.getData().getPaymentId())
                .paymentUrl(result.getData().getPaymentUrl())
                .qrCode(result.getData().getQrCode())
                .expireTime(result.getData().getExpireTime())
                .build();
        }
        catch (Exception e) {
            //抛出异常，拉起支付失败
            throw new BusinessException(40001, "拉起支付失败");
        }
        finally {
            if(lock.isLocked() && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    public PaymentOrderCallbackResponseDTO paymentCallback(PaymentOrderCallbackRequestDTO request) {
        // 查询订单
        OrderDocument order = this.getOrderById(request.getOrderId());

        // 幂等性处理：如果已支付，直接返回成功
        if (order.getStatus() == OrderStatusEnum.PAID || order.getStatus() == OrderStatusEnum.FULFILLING
            || order.getStatus() == OrderStatusEnum.COMPLETED) {
            PaymentOrderCallbackResponseDTO response = new PaymentOrderCallbackResponseDTO();
            response.setOrderId(order.getOrderId());
            response.setOrderNo(order.getOrderNo());
            response.setPaymentStatus("SUCCESS");
            response.setPaidTime(order.getPaymentInfo() != null ? order.getPaymentInfo().getPaidTime() : LocalDateTime.now());
            return response;
        }

        // 验证订单状态
        if (order.getStatus() != OrderStatusEnum.PENDING_PAYMENT) {
            throw new BusinessException(40001, "订单状态不正确");
        }

        // 更新支付信息
        OrderDocument.PaymentInfo paymentInfo = new OrderDocument.PaymentInfo();
        paymentInfo.setPaymentId(UUID.randomUUID().toString());
        paymentInfo.setPaymentMethod(request.getPaymentMethod());
        paymentInfo.setPaymentStatus(request.getPaymentStatus());
        paymentInfo.setTransactionId(request.getTransactionId() != null ?
            request.getTransactionId() : UUID.randomUUID().toString());
        paymentInfo.setPaidAmount(request.getPaidAmount() != null ?
            request.getPaidAmount() : order.getTotalAmount());
        paymentInfo.setPaidTime(LocalDateTime.now());

        order.setPaymentInfo(paymentInfo);

        // 更新订单状态
        if ("SUCCESS".equals(request.getPaymentStatus())) {
            order.setStatus(OrderStatusEnum.PAID);
        } else {
            order.setStatus(OrderStatusEnum.CANCELLED);
        }

        // 保存订单
        this.updateOrder(order);

        // 构建响应
        PaymentOrderCallbackResponseDTO response = new PaymentOrderCallbackResponseDTO();
        response.setOrderId(order.getOrderId());
        response.setOrderNo(order.getOrderNo());
        response.setPaymentStatus(request.getPaymentStatus());
        response.setPaidTime(paymentInfo.getPaidTime());

        return response;
    }
}
